package com.me.study.javaCore.nio;

import org.junit.Test;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;

/**
 * 测试 NIO API：      <p>
 *      1，mark 表示把 position 设定为当前位置、reset 表示把 position 重置到 mark处   <p>
 */
public class NioApiTests {

    @Test
    public void readByBuffer() {
        try (RandomAccessFile aFile = new RandomAccessFile("target/classes/test-file.txt", "rw");
                FileChannel inChannel = aFile.getChannel()) {
            ByteBuffer buf = ByteBuffer.allocate(48);
            inChannel.truncate(1024);// 截取文件，只保留 1024个字符
            int bytesRead = inChannel.read(buf);
            while (bytesRead != -1) {
                // 翻转 buffer，使其可读
                buf.flip();
                while(buf.hasRemaining()){
                    System.out.print((char) buf.get());
                }
                // 翻转 buffer，使其可写
                buf.clear();
                // buf.compact();// 压缩 buffer（未读的数据拷贝到起始位置），使其可写
                bytesRead = inChannel.read(buf);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * http://ifeve.com/file-channel/
     */
    @Test
    public void fileChannel() {
        // FileChannel inChannel = aFile.getChannel();
        String newData = "New String to write to file..." + System.currentTimeMillis();
        ByteBuffer buf = ByteBuffer.allocate(48);
        buf.clear();
        buf.put(newData.getBytes());
        buf.flip();
        while(buf.hasRemaining()) {
            // channel.write(buf);
            System.out.print((char) buf.get());
        }
    }

    /**
     * 如果两个通道中有一个是 FileChannel，那你可以使用 transferFrom、transferTo 直接读写到文件中：    <p>
     *      1，FileChannel.transferFrom() 表示将数据从 任意源channel 传输到 FileChannel；   <p>
     *      2，FileChannel.transferTo() 表示将数据从 FileChannel 传输到其他的 channel。   <p>
     */
    @Test
    public void transfer() {
    }

    /**
     * selector 与 Channel 一起使用时，Channel 必须处于非阻塞模式下。 <p>
     * 这意味着不能将 FileChannel 与 Selector 一起使用，因为 FileChannel 不能切换到非阻塞模式。而套接字通道都可以。
     */
    @Test
    public void selector() throws IOException {
        // Selector selector = Selector.open();
        // channel.configureBlocking(false);
        // SelectionKey selectionkey = channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
        // while(true) {
        //     int readyChannels = selector.select();
        //     if(readyChannels == 0) continue;
        //     Set<SelectionKey> selectedKeys = selector.selectedKeys();
        //     Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
        //     while(keyIterator.hasNext()) {
        //         SelectionKey key = keyIterator.next();
        //         if(key.isAcceptable()) {
        //             // a connection was accepted by a ServerSocketChannel.
        //         } else if (key.isConnectable()) {
        //             // a connection was established with a remote server.
        //         } else if (key.isReadable()) {
        //             // a channel is ready for reading
        //         } else if (key.isWritable()) {
        //             // a channel is ready for writing
        //         }
        //         keyIterator.remove();
        //     }
        // }
    }

}
